package license

import (
	"fmt"

	"github.com/gogf/gf/v2/crypto/gmd5"
	"github.com/gogf/gf/v2/text/gstr"
	"github.com/gogf/gf/v2/util/grand"
)

func NewCodeGenerator() *codeGeneratorService {
	return &codeGeneratorService{}
}

type codeGeneratorService struct {
	number bool
}

func (r *codeGeneratorService) SetNumber() *codeGeneratorService {
	r.number = true

	return r
}

func (r *codeGeneratorService) Generate() string {
	if r.number {
		return r.GenerateNumber()
	}

	return r.GenerateString()
}
func (*codeGeneratorService) GenerateString() string {
	str := grand.Str("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 20)
	str = gstr.ChunkSplit(str, 5, "-")
	return gstr.Trim(str, "-")
}
func (r *codeGeneratorService) GenerateNumber() string {
	src := grand.S(20)

	ascii := r.ascii(r.md5(src))
	part1 := r.rnd1(ascii, 5)
	part4 := r.rnd1(ascii, 5)

	part2Ascii := r.ascii(r.md5(part1 + part4))
	part3Ascii := r.ascii(r.md5(part4 + part1))
	part2Array := []int{1, 3, 5, 7, 9}
	part3Array := []int{0, 2, 4, 6, 8}
	part2 := r.rnd2(part2Ascii, part2Array)
	part3 := r.rnd2(part3Ascii, part3Array)

	return part1 + part2 + part3 + part4
}

// number

func (*codeGeneratorService) md5(source string) string {
	return gstr.Replace(gmd5.MustEncryptString(source), "0", "")
}
func (*codeGeneratorService) ascii(source string) string {
	result := ""

	for _, v := range source {
		result = result + fmt.Sprintf("%d", v)
	}

	return result
}
func (*codeGeneratorService) rnd1(source string, count int) string {
	length := len(source) - 1
	result := ""

	for i := 0; i < count; i++ {
		index := grand.N(0, length)
		result = result + string(source[index])
	}

	return result
}
func (*codeGeneratorService) rnd2(source string, indices []int) string {
	result := ""

	for _, v := range indices {
		result = result + string(source[v])
	}

	return result
}
